<?php
namespace App\Models;

use App\Models\ComModel;

class MenuModel extends ComModel
{

    protected $ids;

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 条件查询
     */
    private function _where(&$select, $data)
    {
        if ($data) {
            // 时间搜索
            if (isset($data['name']) && $data['name']) {
                $select->where('name', $data['name']);
            }

            if (isset($data['pid'])) {
                $select->where('pid', $data['pid']);
            }
        }
        return $data;
    }

    /**
     * 数据分页显示
     */
    public function limit_page($page = 0, $size = 10, $total = 0, $param = [])
    {
        ams_clean_xss($param);
        $param['pid'] = 0;
        $page = max(1, (int) $page);
        $total = (int) $total;
        if ($param) {
            $param = esc($param);
        }
        unset($param['page']);
        if ($size > 0 && !$total) {
            $select = $this->db->table('admin_menu')->select('count(*) as total');
            $param = $this->_where($select, $param);
            $query = $select->get();
            if (!$query) {
                log_message('error', '数据查询失败：admin_menu');
                return [[], $total, $param];
            }
            $data = $query->getRowArray();
            $total = (int) $data['total'];
            $param['total'] = $total;
            unset($select);
            if (!$total) {
                return [[], $total, $param];
            }
        }

        $select = $this->db->table('admin_menu');
        $param = $this->_where($select, $param);
        $size > 0 && $select->limit($size, $size * ($page - 1));
        $query = $select->orderBy('id', 'asc')->get();
        if (!$query) {
            log_message('error', '数据查询失败：admin_menu');
            return [[], $total, $param];
        }
        $data = $query->getResultArray();

        if ($data) {
            foreach ($data as $k => $v) {
                $sons = $this->db->table('admin_menu')->where('pid', $v['id'])->get()->getResultArray();
                if ($sons) {
                    $data = array_merge($data, $sons);
                }
            }
            $tree = new \App\Libraries\Tree();
            $data = $tree->get($data);
        }
        $param['total'] = $total;
        return [$data, $total, $param];
    }

    // 新增后台菜单
    public function add($table, $pid = 0, $data = [])
    {
        $pid = intval($pid);
        $table = esc($table);

        if (!$table) {
            return ams_rt(1, '数据库不存在');
        }
        if ($pid) {
            $row = $this->db->table($table . '_menu')->select('id,pid')->where('id', $pid)->get()->getRowArray();
            if (!$row) {
                return ams_rt(1, '上级菜单不存在');
            }
            $this->db->table($table . '_menu')->where('id', $pid)->update(['child' => 1]);
        } else {
            $pid = 0;
        }

        $data = esc($data);

        if (!$data['name'] && !$data['uri']) {
            return ams_rt(1, '请填写菜单名称 和 URI地址');
        }

        if (isset($data['uri']) && $data['uri'] && $this->db->table($table . '_menu')->where('child', 0)->where('uri', $data['uri'])->countAllResults()) {
            return ams_rt(1, '菜单已存在');
        }

        $this->db->table($table . '_menu')->insert([
            'pid' => $pid,
            'name' => $data['name'],
            'uri' => $data['uri'] ?? '',
            'param' => $data['param'] ?? '',
            'url' => $data['url'] ?? '',
            'icon' => $data['icon'] ?? '',
            'show' => 1,
            'mark' => $data['mark'] ?? '',
            'displayorder' => isset($data['displayorder']) ? intval($data['displayorder']) : 0,
        ]);
        $id = $this->db->insertID();
        if ($id) {
            $this->cacheData();
            return ams_rt(0, '成功', $id);
        }
        return ams_rt(1, '失败');

    }

    // 修改菜单
    public function edit($table, $id, $data)
    {
        $data = esc($data);
        $this->db->table('admin_menu')->where('id', (int) $id)->update($data);
        if ($this->db->affectedRows()) {
            $this->cacheData();
        }
        return $id;
    }

    // 后台菜单合并
    private function _admin_add_menu($menu, $new)
    {
        foreach ($new as $mk1 => $top) {
            // 合并顶级菜单
            if ($mk1 && isset($menu[$mk1])) {
                // 它存在分组菜单时才合并
                if ($top['left']) {
                    foreach ($top['left'] as $mk2 => $left) {
                        if ($mk2 && isset($menu[$mk1]['left'][$mk2])) {
                            foreach ($left['link'] as $link) {
                                $menu[$mk1]['left'][$mk2]['link'][] = $link;
                            }
                        } else {
                            $menu[$mk1]['left'][] = $left;
                        }
                    }
                }
            } else {
                $menu[$mk1] = $top;
            }
        }
        return $menu;
    }

    // 用户菜单合并
    private function _user_add_menu($menu, $new)
    {

        foreach ($new as $mk1 => $top) {
            // 合并顶级菜单
            if ($mk1 && isset($menu[$mk1])) {
                // 它存在下级菜单时才合并
                if ($top['link']) {
                    foreach ($top['link'] as $left) {
                        $menu[$mk1]['link'][] = $left;
                    }
                }
            } else {
                $menu[$mk1] = $top;
            }
        }

        return $menu;
    }

    // 初始化菜单
    public function init($table = '')
    {
        $table = ams_safe_replace($table);

        if (is_file(WRITEPATH . 'install/menu.php')) {
            $default = require WRITEPATH . 'install/menu.php';
        } else {
            // 框架主菜单
            return ams_rt(1, '初始化菜单文件(menu.php)不存在');
        }

        if (!$table || !in_array($table, ['user','admin'])) {
            $table = 'admin';
        }

        $menu = $default[$table] ?? [];

        // 清空表
        $this->db->table($table . '_menu')->truncate();
        $this->db->table($table . '_menu')->emptyTable();

        $this->addInstallMenu($table, $menu);

        //安装项目
        // if (is_file(WRITEPATH . 'install/menu_site.php')) {
        //     $menu = require WRITEPATH . 'install/menu_site.php';
        //     if ($menu && is_array($menu)) {
        //         $this->addInstallMenu($table, $menu[$table] ?? []);
        //     }
        // }

        return ams_rt(0, '操作成功');
    }

    //添加菜单
    public function addInstallMenu($table, $menu)
    {
        $pid = 0;
        foreach ($menu as $top) {
            // 插入顶级菜单
            $rt = $this->add($table, 0, $top);
            if ($rt['code'] == 0) {
                $pid = $rt['data'];
            } else {
                continue;
            }
            // 插入分组菜单
            if ($pid && isset($top['child']) && $top['child']) {

                foreach ($top['child'] as $second) {

                    $rt2 = $this->add($table, $pid, $second);

                    //最多三层
                    if ($rt2['code'] == 0 && isset($second['child']) && $second['child']) {
                        $pid = $rt2['data'];
                        foreach ($second['child'] as $third) {
                            $this->add('admin', $pid, $third);
                        }
                    }

                }
            }
        }
    }

    // 初始化菜单
    public function init_apps($dirname, $table = '')
    {
        $file = APPSPATH . ucfirst($dirname) . '/Config/Menu.php';
        if (is_file($file)) {
            $menuDefault = require $file;
        } else {
            // 框架主菜单
            return ams_rt(1, 'APP菜单配置文件(Menu.php)不存在');
        }

        if (!$table) {
            $table = 'admin';
        }

        $mark = 'app-' . strtolower($dirname);
        $menu = $menuDefault[$table] ?? [];

        $this->addInstallMenu($table, $menu);

        // foreach ($menu as $top) {
        //     $top['mark'] = $mark;
        //     // 插入顶级菜单
        //     $rt = $this->add('admin', 0, $top);
        //     if ($rt['code'] == 0) {
        //         $top_id = $rt['data'];
        //     } else {
        //         return false;
        //     }
        //     // 插入分组菜单
        //     if ($top_id) {
        //         foreach ($top['child'] as $left) {
        //             $left['mark'] = $mark;
        //             $this->add('admin', $top_id, $left);
        //         }
        //     }
        // }
        return ams_rt(0, '操作成功');
    }

    public function del_apps($dirname)
    {
        $dirname = esc($dirname);
        $data1 = $this->db->table('admin_menu')->select('id')->where('mark', 'app-' . strtolower($dirname))->get()->getResultArray();
        if ($data1) {
            foreach ($data1 as $v) {
                $ids[] = $v['id'];
            }
            $this->_delete('admin', $ids);
        }

    }

    public function setdisplayorder($id, $displayorder)
    {
        return $this->displayorder($this->table, $id, $displayorder);
    }

    public function switchHidden($id, $value)
    {
        if (!$id) {
            return ams_rt(1, '参数错误');
        }
        $row = $this->db->table('admin_menu')->select('id,name,show')->where('id', $id)->get()->getRowArray();
        if (!$row) {
            return ams_rt(1, '数据不存在');
        }
        if ($value == 1) {
            $this->db->table('admin_menu')->where('id', $id)->update(['show' => 1]);
        } else {
            $this->db->table('admin_menu')->where('id', $id)->update(['show' => 0]);
        }
        return ams_rt(0, '操作成功', $row);
    }

    // 获取单个
    public function getRowData($table, $id)
    {
        return $this->db->table($table . '_menu')->where('id', $id)->get()->getRowArray();
    }

    // 获取菜单
    public function gets($table)
    {

        $menu = [];
        $data = $this->db->table($table . '_menu')->orderBy('displayorder ASC,id ASC')->get()->getResultArray();

        if ($data) {
            $tree = new \App\Libraries\Tree();
            $menu = $tree->get($data);
        }
        return $menu;
    }

    // 获取顶级菜单
    public function get_top($table)
    {
        if (!$table) {
            return false;
        }
        $menu = [];
        $data = $this->db->table($table . '_menu')->where('pid', 0)->orderBy('displayorder ASC,id ASC')->get()->getResultArray();

        if ($data) {
            foreach ($data as $t) {
                $menu[$t['id']] = $t;
            }
        }
        return $menu;
    }

    public function _delete($table, $ids)
    {
        $table = ams_safe_replace($table);
        if (!$table) {
            $res = ams_rt(1, '参数不全');
        } elseif (!$ids) {
            $res = ams_rt(1, '参数不全');
        } else {
            $this->ids = [];
            foreach ($ids as $id) {
                $this->_get_id($table, (int) $id);
            }
            $this->ids && $this->db->table($table . '_menu')->whereIn('id', $this->ids)->delete();
            $res = ams_rt(0, '操作成功');
        }
        $this->cacheData();
    }

    // 获取自己id和子id
    private function _get_id($table, $id)
    {

        if (!$id) {
            return false;
        }

        $this->ids[$id] = $id; //自己

        $data = $this->db->table($table . '_menu')->where('pid', $id)->get()->getResultArray();

        if (!$data) {
            return false;
        }
        foreach ($data as $t) {
            $this->ids[$t['id']] = $t['id'];
            $this->_get_id($table, (int) $t['id']);
        }
    }

    /**
     * 父级菜单选择
     *
     * @param    intval    $level    级别
     * @param    intval    $id        选中项id
     * @param    intval    $name    select部分
     * @return    string
     */
    public function parent_select($table, $level = 0, $id = null, $name = null)
    {
        $level = intval($level);
        $id = intval($id);
        $select = $name ? $name : '<select class="form-control" name="data[pid]">';

        if ($level) {
            $topdata = $this->db->table($table . '_menu')->select('id,name')->where('pid', $id)->get()->getResultArray();
            foreach ($topdata as $t) {
                $select .= '<option value="' . $t['id'] . '"' . ($id == $t['id'] ? ' selected' : '') . '>' . $t['name'] . '</option>';
            }
        } else {
            //不存在上级
            $select .= '<option value="0">顶级菜单</option>';
        }

        $select .= '</select>';

        return $select;
    }

    // 缓存
    public function cacheData()
    {

        $cache = \Config\Services::cache();

        $menu = [
            'admin' => [],
            'user' => [],
        ];
        $madmin = [];

        // admin 菜单
        $data = $this->db->table('admin_menu')->where('show', 1)->orderBy('displayorder ASC,id ASC')->get()->getResultArray();
        if ($data) {
            $rows = $this->db->table('rbac_role')->select('id,auth')->get()->getResultArray();
            foreach ($rows as $arow) {
                if ($arow['auth']) {
                    $auth = json_decode($arow['auth'], true);
                }
                $list = [];
                foreach ($data as $t) {
                    if ($t['pid'] == 0) {
                        $list[$t['id']] = $t;
                        foreach ($data as $m) {
                            if ($arow['id'] != 1 && (!isset($auth) || !$auth || !in_array($m['uri'], $auth))) {
                                continue;
                            }
                            if ($m['pid'] == $t['id']) {
                                if (!$m['url'] && $m['uri']) {
                                    $m['url'] = url($m['uri'], $m['param']);
                                }
                                $list[$t['id']]['left'][$m['id']] = $m;

                                //第三层
                                foreach ($data as $third) {
                                    if ($arow['id'] != 1 && (!$auth || !in_array($m['uri'], $auth))) {
                                        continue;
                                    }
                                    if ($third['pid'] == $m['id']) {
                                        if (!$third['url'] && $third['uri']) {
                                            $third['url'] = url($third['uri'], $third['param']);
                                        }
                                        $list[$t['id']]['left'][$m['id']]['left'][] = $third;
                                    }
                                }

                            }
                        }
                    }
                }
                $madmin[$arow['id']] = $menu['admin'] = $list;
                $cache->save('menu-admin-' . $arow['id'], $menu['admin'], YEAR);
            }
        }

        $session = \Config\Services::session();
        $admin = $session->get('admin');
        if ($admin && isset($admin['roleid']) && $admin['roleid']) {
            $menu['admin'] = $madmin[$admin['roleid']] ?? [];
        }
        return $menu;
    }

}
